// b18.v
// Verilog version, rewritten by Li Shen, Aug 2002
// Institute of Computing Technology, Chinese Academy of Sciences
// The original VHDL version is b18.vhd from Politecnico di Torino

module b14 (clock, reset, datai, rd, wr, addr, datao);
input clock;
input reset;
input [31:0] datai; //signed
output rd;
output wr;
output [19:0] addr;
output [31:0] datao; //signed
//////
wire clock;
wire reset;
wire [31:0] datai; //signed
reg rd;
reg wr;
reg [19:0] addr;
reg [31:0] datao; //signed
/////
reg [31:0] reg0; //signed
reg [31:0] reg1; //signed
reg [31:0] reg2; //signed
reg [31:0] reg3; //signed
reg B;
reg [19:0] MAR;
reg [31:0] MBR; //signed
reg [1:0] mf;
reg [2:0] df;
reg cf;
reg [3:0] ff;
reg [19:0] tail;
reg [31:0] IR; //signed
reg state;
reg [31:0] r,m,t; //signed
reg [31:0] d; //signed
reg [31:0] temp; //signed
reg [1:0] s;
reg [32:0] a; //signed
parameter FETCH=0, EXEC=1;
/////
always @(posedge clock)
begin
  if (reset)
  begin
      MAR = 0;
      MBR = 0;
      IR = 0;
      d = 0;
      r = 0;
      m = 0;
      s = 0;
      temp = 0;
      mf = 0;
      df = 0;
      ff = 0;
      cf = 0;
      tail = 0;
      B = 0;
      reg0 = 0;
      reg1 = 0;
      reg2 = 0;
      reg3 = 0;
      addr <= 0;
      rd <= 0;
      wr <= 0;
      datao <= 0;
      state = FETCH;
  end
  else
  begin
      rd <= 0;
      wr <= 0;
      case (state)
      FETCH:
      begin
        MAR = reg3 & 20'hfffff;
	addr <= MAR;
	rd <= 1;
	MBR = datai;
        IR = MBR;
	state = EXEC;
      end
      EXEC:
      begin
	if (IR[31]) //<0
	  IR = -IR;
	mf = (IR >> 27) & 3 ;
	df = (IR >> 24) & 7;
	ff = (IR >> 19) & 15;
	cf = (IR >> 23) & 1;
	tail = IR & 20'hfffff;
        reg3 = ((reg3 & 32'h1fffffff)+ 8);
	s = (IR >> 29) & 3;
	case (s)
	0: r = reg0;
	1: r = reg1;
	2: r = reg2;
	3: r = reg3;
	endcase
	case (cf)
	1:
        begin
	  case (mf)
	  0:   m = tail;
	  1: begin
               m = datai;
	       addr <= tail;
	       rd <= 1;
             end
	  2: begin
               addr <= (tail + reg1) & 20'hfffff;
	       rd <= 1;
               m = datai;
             end
	  3: begin
               addr <= (tail + reg2) & 20'hfffff;
	       rd <= 1;
               m = datai;
             end
	  endcase
	  case (ff)
	  0: begin
	       a = {r[31],r} - {m[31],m};
	       if (a[32]) B = 1; //r<m
               else	  B = 0;
	     end
	  1: begin
	       a = {r[31],r} - {m[31],m};
	       if (!a[32]) B = 1; //not(r<m)
               else	   B = 0;
	     end
	  2: if (r == m) B = 1;
             else	  B = 0; 
	  3: if (r != m) B = 1;
             else	  B = 0; 
	  4: begin
	       a = {m[31],m} - {r[31],r};
	       if (!a[32]) B = 1; //not(m<r)
               else	   B = 0;
	     end
	  5: begin
	       a = {m[31],m} - {r[31],r};
	       if (a[32]) B = 1; //m<r
               else	  B = 0;
	     end
	  6: begin
	       if (!r[31] && r>32'h3fffffff) r = r - 32'h40000000;
	       a = {r[31],r} - {m[31],m};
	       if (a[32]) B = 1; //r<m
               else	  B = 0;
	     end 
	  7: begin
	       if (!r[31] && r>32'h3fffffff) r = r - 32'h40000000;
	       a = {r[31],r} - {m[31],m};
	       if (!a[32]) B = 1; //not(r<m)
               else	   B = 0;
	     end 
	  8: begin
	       a = {r[31],r} - {m[31],m};
	       if (a[32] || B) B = 1; //r<m
               else	       B = 0;
	     end 
	  9: begin
	       a = {r[31],r} - {m[31],m};
	       if (!a[32] || B) B = 1; //not(r<m)
               else	        B = 0;
	     end 
	  10: if (r == m || B) B = 1;
              else		B = 0;
	  11: if (r != m || B) B = 1;
              else	 	   B = 0;
	  12: begin
	        a = {m[31],m} - {r[31],r};
	        if (!a[32] || B) B = 1; //not(m<r)
                else	         B = 0;
	      end
	  13: begin
	        a = {m[31],m} - {r[31],r};
	        if (a[32] || B) B = 1; //m<r
                else	        B = 0;
	      end
	  14: begin
	       if (!r[31] && r>32'h3fffffff) r = r - 32'h40000000;
	       a = {r[31],r} - {m[31],m};
	       if (a[32] || B) B = 1; //r<m
               else	       B = 0;
	      end 
	  15: begin
	       if (!r[31] && r>32'h3fffffff) r = r - 32'h40000000;
	       a = {r[31],r} - {m[31],m};
	       if (!a[32] || B) B = 1; //not(r<m)
               else	        B = 0;
	      end 
	  endcase
	end
	0:
	begin
	  if (df != 7)
	  begin
	    if (df == 5)
	    begin
	         if (!B) d = 3;
	    end
	    else if (df == 4)
	    begin
	         if (B) d = 3;
	    end
	    else if (df == 3) d = 3;
	    else if (df == 2) d = 2;
	    else if (df == 1) d = 1;
	    else if (df == 0) d = 0;

	    case (ff)
	    0:
	    begin
	      case (mf)
	      0:   m = tail;
	      1: begin
		   m = datai;
		   addr <= tail;
		   rd <= 1;
		 end
	      2: begin
		  addr <= (tail + reg1) & 20'hfffff;
		  rd <= 1;
                  m = datai;
		 end
	      3: begin
		  addr <= (tail + reg2) & 20'hfffff;
		  rd <= 1;
                  m = datai;
		 end
	      endcase
	      t = 0;
	      case (d)
	      0: reg0 = t - m;
	      1: reg1 = t - m;
	      2: reg2 = t - m;
	      3: reg3 = t - m;
	      endcase
	    end
	    1:
	    begin
	      case (mf)
	      0:   m = tail;
	      1: begin
		   m = datai;
		   addr <= tail;
		   rd <= 1;
		 end
	      2: begin
		   addr <= (tail + reg1) & 20'hfffff;
		   rd <= 1;
                   m = datai;
		 end
	      3: begin
		   addr <= (tail + reg2) & 20'hfffff;
		   rd <= 1;
                   m = datai;
		 end
	      endcase
	      reg2 = reg3; 
	      reg3 = m;
	    end
	    2:
	    begin
	      case (mf)
	      0:   m = tail;
	      1: begin
		   m = datai;
		   addr <= tail;
		   rd <= 1;
		 end
	      2: begin
		   addr <= (tail + reg1) & 20'hfffff;
		   rd <= 1;
                   m = datai;
		 end
	      3: begin
		   addr <= (tail + reg2) & 20'hfffff;
		   rd <= 1;
                   m = datai;
		 end
	      endcase
	      case (d)
	      0: reg0 = m;
	      1: reg1 = m;
	      2: reg2 = m;
	      3: reg3 = m;
	      endcase
	    end
	    3:
	    begin 
	      case (mf)
	      0:  m = tail;
	      1: begin
		  m = datai;
		  addr <= tail;
		  rd <= 1;
		 end
	      2: begin
		   addr <= (tail + reg1) & 20'hfffff;
		   rd <= 1;
                   m = datai;
		 end
	      3: begin
		   addr <= (tail + reg2) & 20'hfffff;
		   rd <= 1;
                   m = datai;
		 end
	      endcase
	      case (d)
	      0: reg0 = m;
	      1: reg1 = m;
	      2: reg2 = m;
	      3: reg3 = m;
	      endcase
	    end
	    4:
	    begin
	      case (mf)
	      0: m = tail;
	      1: begin
		   m = datai;
		   addr <= tail;
		   rd <= 1;
		 end
	      2: begin
		   addr <= (tail + reg1) & 20'hfffff;
		   rd <= 1;
                   m = datai;
		 end
	      3: begin
		   addr <= (tail + reg2) & 20'hfffff;
		   rd <= 1;
                   m = datai;
		 end
	      endcase
	      case (d)
	      0: reg0 = (r + m) & 32'h3fffffff;
	      1: reg1 = (r + m) & 32'h3fffffff;
	      2: reg2 = (r + m) & 32'h3fffffff;
	      3: reg3 = (r + m) & 32'h3fffffff;
	      endcase
	    end
	    5:
	    begin
	      case (mf)
	      0:   m = tail;
	      1: begin
		   m = datai;
		   addr <= tail;
		   rd <= 1;
		 end
	      2: begin
		   addr <= (tail + reg1) & 20'hfffff;
		   rd <= 1;
                   m = datai;
		 end
	      3: begin
		   addr <= (tail + reg2) & 20'hfffff;
		   rd <= 1;
                   m = datai;
		 end
	      endcase
	      case (d)
	      0: reg0 = (r + m) & 32'h3fffffff;
	      1: reg1 = (r + m) & 32'h3fffffff;
	      2: reg2 = (r + m) & 32'h3fffffff;
	      3: reg3 = (r + m) & 32'h3fffffff;
	      endcase
	    end
	    6:
	    begin
	      case (mf)
	      0:   m = tail;
	      1: begin
		   m = datai;
		   addr <= tail;
		   rd <= 1;
		 end
	      2: begin
		   addr <= (tail + reg1) & 20'hfffff;
		   rd <= 1;
                   m = datai;
		 end
	      3: begin
		   addr <= (tail + reg2) & 20'hfffff;
		   rd <= 1;
                   m = datai;
		 end
	      endcase
	      case (d)
	      0: reg0 = (r - m) & 32'h3fffffff;
	      1: reg1 = (r - m) & 32'h3fffffff;
	      2: reg2 = (r - m) & 32'h3fffffff;
	      3: reg3 = (r - m) & 32'h3fffffff;
	      endcase
	    end
	    7:
	    begin
	      case (mf)
	      0:   m = tail;
	      1: begin
		   m = datai;
		   addr <= tail;
		   rd <= 1;
		 end
	      2: begin
		   addr <= (tail + reg1) & 20'hfffff;
		   rd <= 1;
                   m = datai;
		 end
	      3: begin
		   addr <= (tail + reg2) & 20'hfffff;
		   rd <= 1;
                   m = datai;
		 end
	      endcase
	      case (d)
	      0: reg0 = (r - m) & 32'h3fffffff;
	      1: reg1 = (r - m) & 32'h3fffffff;
	      2: reg2 = (r - m) & 32'h3fffffff;
	      3: reg3 = (r - m) & 32'h3fffffff;
	      endcase
	    end
	    8:
	    begin
	      case (mf)
	      0:   m = tail;
	      1: begin
		   m = datai;
		   addr <= tail;
		   rd <= 1;
		 end
	      2: begin
		   addr <= (tail + reg1) & 20'hfffff;
		   rd <= 1;
                   m = datai;
		 end
	      3: begin
		   addr <= (tail + reg2) & 20'hfffff;
		   rd <= 1;
                   m = datai;
		 end
	      endcase
	      case (d)
	      0: reg0 = (r + m) & 32'h3fffffff;
	      1: reg1 = (r + m) & 32'h3fffffff;
	      2: reg2 = (r + m) & 32'h3fffffff;
	      3: reg3 = (r + m) & 32'h3fffffff;
	      endcase
	    end
	    9:
	    begin
	      case (mf)
	      0:   m = tail;
	      1: begin
		   m = datai;
		   addr <= tail;
		   rd <= 1;
		 end
	      2: begin
		   addr <= (tail + reg1) & 20'hfffff;
		   rd <= 1;
                   m = datai;
		 end
	      3: begin
		   addr <= (tail + reg2) & 20'hfffff;
		   rd <= 1;
                   m = datai;
		 end
	      endcase
	      case (d)
	      0: reg0 = (r - m) & 32'h3fffffff;
	      1: reg1 = (r - m) & 32'h3fffffff;
	      2: reg2 = (r - m) & 32'h3fffffff;
	      3: reg3 = (r - m) & 32'h3fffffff;
	      endcase
	    end
	    10: 
	    begin
	      case (mf)
	      0:   m = tail;
	      1: begin
		   m = datai;
		   addr <= tail;
		   rd <= 1;
		 end
	      2: begin
		   addr <= (tail + reg1) & 20'hfffff;
		   rd <= 1;
                   m = datai;
		 end
	      3: begin
		   addr <= (tail + reg2) & 20'hfffff;
		   rd <= 1;
                   m = datai;
		 end
	      endcase
	      case (d)
	      0: reg0 = (r + m) & 32'h3fffffff;
	      1: reg1 = (r + m) & 32'h3fffffff;
	      2: reg2 = (r + m) & 32'h3fffffff;
	      3: reg3 = (r + m) & 32'h3fffffff;
	      endcase
	    end
	    11:
	    begin
	      case (mf)
	      0:   m = tail;
	      1: begin
		   m = datai;
		   addr <= tail;
		   rd <= 1;
		 end
	      2: begin
		   addr <= (tail + reg1) & 20'hfffff;
		   rd <= 1;
                   m = datai;
		 end
	      3: begin
		   addr <= (tail + reg2) & 20'hfffff;
		   rd <= 1;
                   m = datai;
		 end
	      endcase
	      case (d)
	      0: reg0 = (r - m) & 32'h3fffffff;
	      1: reg1 = (r - m) & 32'h3fffffff;
	      2: reg2 = (r - m) & 32'h3fffffff;
	      3: reg3 = (r - m) & 32'h3fffffff;
	      endcase
	    end
	    12:
	    begin
	      case (mf)
	      0:   if (r[31]) t = -(-r >> 1);
		   else       t = r >> 1;
              1: begin
		   if (r[31]) t = -(-r >> 1);
		   else       t = r >> 1;
		   if (B) t = t & 32'h1fffffff;
		 end
	      2: t = (r & 32'h1fffffff) << 1;
	      3: begin
		   t = (r & 32'h1fffffff) << 1;
		   if (!t[31] && t > 32'h3fffffff) B = 1;
		   else			           B = 0;
		 end
	      endcase
	      case (d)
	      0: reg0 = t;
	      1: reg1 = t;
	      2: reg2 = t;
	      3: reg3 = t;
	      endcase
	    end
	    endcase
	  end
	  else
	  begin
	    if (df == 7)
	    begin
	      case (mf)
	      0: m = tail;
	      1: m = tail;
	      2: m = (reg1 & 20'hfffff) + (tail & 20'hfffff);
	      3: m = (reg2 & 20'hfffff) + (tail & 20'hfffff);
	      endcase
	      addr <= m & 20'hfffff;
	      wr <=1;
	      datao <= r;
	    end
	  end
	end
	endcase
	state = FETCH;
      end
      endcase
  end
end
endmodule

//////////

module b15 (CLOCK, RESET, NA_n, BS16_n, READY_n, HOLD, Datai,
	    W_R_n, D_C_n, M_IO_n, ADS_n, BE_n, Address, Datao);
input CLOCK;
input RESET;
input NA_n;
input BS16_n;
input READY_n;
input HOLD;
input [31:0] Datai; //signed
output W_R_n;
output D_C_n;
output M_IO_n;
output ADS_n;
output [3:0] BE_n;
output [29:0]Address;
output [31:0] Datao; //signed
/////
wire CLOCK;
wire RESET;
wire NA_n;
wire BS16_n;
wire READY_n;
wire HOLD;
wire [31:0] Datai; //signed
reg W_R_n;
reg D_C_n;
reg M_IO_n;
reg ADS_n;
reg [3:0] BE_n;
reg [29:0] Address;
reg [31:0] Datao; //signed
/////
reg StateNA;
reg StateBS16;
reg RequestPending;
reg NonAligned;
reg ReadRequest;
reg MemoryFetch;
reg CodeFetch;
reg [3:0] ByteEnable;
reg [1:0] DataWidth;
reg [2:0] State;
reg [31:0] EAX; //signed
reg [31:0] EBX; //signed
reg [31:0] rEIP; //signed

parameter Pending=1, NotPending=0, WidthByte=0, WidthWord=1, WidthDword=2;

parameter StateInit=0, StateTi=1, StateT1=2,  StateT2=3;
parameter StateT1P=4,  StateTh=5, StateT2P=6, StateT2I=7;

parameter REP=8'hF3, REPNE=8'hF2, LOCK=8'hF0;

parameter CSsop=8'h2E, SSsop=8'h36, DSsop=8'h3E, ESsop=8'h26;
parameter FSsop=8'h64, GSsop=8'h65, OPsop=8'h66, ADsop=8'h67;

parameter MOV_al_b=8'hB0,         MOV_eax_dw=8'hB8;
parameter MOV_ebx_dw=8'hBB,       MOV_ebx_eax=8'h89;
parameter MOV_eax_ebx=8'h8B,      IN_al=8'hE4;
parameter OUT_al=8'hE6,           ADD_al_b=8'h04;
parameter ADD_ax_w=8'h05,         ROL_eax_b=8'hD1;
parameter ROL_al_1=8'hD0,         ROL_al_n =8'hC0;
parameter INC_eax=8'h40,          INC_ebx=8'h43;
parameter JMP_rel_short=8'hEB,    JMP_rel_near=8'hE9;
parameter JMP_intseg_immed=8'hEA, HLT=8'hF4;
parameter WAITx=8'h9B,            NOP=8'h90;
///// P0
reg [31:0] a1; //signed

always @(posedge CLOCK)
    begin
      if (RESET)
	begin
	    BE_n <= 0;
            Address <= 0;
            W_R_n <= 0;
            D_C_n <= 0;
            M_IO_n <= 0;
	    ADS_n <= 0;

	    State <= StateInit;

	    StateNA <= 0;
	    StateBS16 <= 0;
	    DataWidth <= 0;
	end
      else
        case (State)
	    StateInit:
	    begin
		D_C_n <= 1;
		ADS_n <= 1;
		State <= StateTi;
		StateNA <= 1;
		StateBS16 <= 1;
		DataWidth <= 2;
		State <= StateTi;
	    end
            StateTi:
	    begin
                if (RequestPending == Pending)
                    State <= StateT1;
                else if (HOLD)
                    State <= StateTh;
                else
                    State <= StateTi;
	    end
            StateT1:
	    begin
                // Address <= rEIP/4;
                // fs 062299
	      if (rEIP[31]) a1 = -(-rEIP >> 2);
	      else          a1 = rEIP >> 2;
	      Address <= a1 & 32'h3fffffff;
	      BE_n <= ByteEnable;
	      M_IO_n <= MemoryFetch;
	      if (ReadRequest == Pending)
		W_R_n <= 0;
	      else
		W_R_n <= 1;
	      if (CodeFetch == Pending)
		D_C_n <= 0;
	      else
		D_C_n <= 1;
	      ADS_n <= 0;
	      State <= StateT2;
	    end
            StateT2:
	    begin
                if (!READY_n && !HOLD && RequestPending==Pending)
                    State <= StateT1;
//              else if (READY_N && NA_n)
                else if ((RequestPending==Pending||HOLD)&&READY_n&&!NA_n)
                    State <= StateT2I;
                else if (RequestPending==Pending&&!HOLD&&READY_n&&!NA_n)
                    State <= StateT2P;
                else if (RequestPending==NotPending && !HOLD && !READY_n)
                    State <= StateTi;
                else if (HOLD && READY_n)
                    State <= StateTh;
		else
		    State <= StateT2;
		StateBS16 <= BS16_n;
		if (!BS16_n)
		    DataWidth <= WidthWord;
		else
		    DataWidth <= WidthDword;
		StateNA <= NA_n;
		ADS_n <= 1;
	    end
            StateT1P:
	    begin
                if (!NA_n && !HOLD && RequestPending==Pending)
                    State <= StateT2P;
                else if (!NA_n && (HOLD || RequestPending==NotPending))
                    State <= StateT2I;
                else if (NA_n)
                    State <= StateT2;
		else
		    State <= StateT1P;
		StateBS16 <= BS16_n;
		if (!BS16_n)
		    DataWidth <= WidthWord;
		else
		    DataWidth <= WidthDword;
		StateNA <= NA_n;
		ADS_n <= 1;
	    end
            StateTh:
	    begin
                if (!HOLD && RequestPending==Pending)
                    State <= StateT1;
                else if (!HOLD && RequestPending==NotPending)
                    State <= StateTi;
		else
		    State <= StateTh;
	    end
            StateT2P:
	    begin
	        // Address <= rEIP/2;
                // fs 990629
	        if (rEIP[31]) a1 = -(-rEIP >> 1);
	        else          a1 = rEIP >> 1;
	        Address <= a1 & 32'h3fffffff;
                BE_n <= ByteEnable;
                M_IO_n <= MemoryFetch;
                if (ReadRequest==Pending)
                    W_R_n <= 0;
                else
                    W_R_n <= 1;
                if (CodeFetch==Pending)
                    D_C_n <= 0;
                else
                    D_C_n <= 1;
		ADS_n <= 0;
                if (!READY_n)
                    State <= StateT1P;
		else
		    State <= StateT2P;
	    end
            StateT2I:
	    begin
                if (READY_n && RequestPending==Pending && !HOLD)
                    State <= StateT2P;
                else if (!READY_n && HOLD)
                    State <= StateTh;
                else if (!READY_n && !HOLD && RequestPending==Pending)
                    State <= StateT1;
                else if (!READY_n && !HOLD && RequestPending==NotPending)
                    State <= StateTi;
		else
		    State <= StateT2I;
	    end
        endcase
    end
///// P1
reg [7:0] InstQueue[15:0];
reg [4:0] InstQueueRd_Addr;
reg [4:0] InstQueueWr_Addr;
reg [31:0] InstAddrPointer; //signed
reg [31:0] PhyAddrPointer; //signed
reg Extended;
reg More;
reg Flush;
reg [15:0] lWord;
reg [14:0] uWord;
reg [31:0] fWord; //signed
reg [3:0] State2;
reg [31:0] a2; //signed

parameter InstQueueLimit = 15;
parameter Si = 0, S1 = 1, S2 = 2, S3 = 3, S4 = 4;
parameter S5 = 5, S6 = 6, S7 = 7, S8 = 8, S9 = 9;

always @(posedge CLOCK)
    begin
	if (RESET)
	begin
	    State2 = Si;
	    InstQueue[0]=0; InstQueue[1]=0; InstQueue[2]=0; InstQueue[3]=0; 
	    InstQueue[4]=0; InstQueue[5]=0; InstQueue[6]=0; InstQueue[7]=0; 
	    InstQueue[8]=0; InstQueue[9]=0; InstQueue[10]=0; InstQueue[11]=0; 
	    InstQueue[12]=0; InstQueue[13]=0; InstQueue[14]=0; InstQueue[15]=0; 
	    InstQueueRd_Addr = 0;
	    InstQueueWr_Addr = 0;
	    InstAddrPointer = 0;
	    PhyAddrPointer = 0;
	    Extended = 0;
	    More = 0;
	    Flush = 0;
	    lWord = 0;
	    uWord = 0;
	    fWord = 0;
	    CodeFetch <= 0;
            Datao <= 0;
	    EAX <= 0;
	    EBX <= 0;
	    rEIP <= 0;
	    ReadRequest <= 0;
	    MemoryFetch <= 0;
	    RequestPending <= 0;
	end
	else
	case (State2)
	Si:
	begin
            PhyAddrPointer = rEIP;
            InstAddrPointer = PhyAddrPointer;
	    State2 = S1;
	    rEIP <= 20'hFFFF0;
	    ReadRequest <= 1;
	    MemoryFetch <= 1;
	    RequestPending <= 1;
	end
	S1:
	begin
            RequestPending <= Pending;
            ReadRequest <= Pending;
            MemoryFetch <= Pending;
            CodeFetch <= Pending;
	    if (!READY_n)
		State2 = S2;
	    else
		State2 = S1;
	end
	S2:
	begin
            RequestPending <= NotPending;
            InstQueue[InstQueueWr_Addr] = Datai & 255;
            InstQueueWr_Addr = (InstQueueWr_Addr+ 1) & 15;
//            InstQueue(InstQueueWr_Addr) = (Datai / 256) % 256;
            InstQueue[InstQueueWr_Addr] = Datai & 255;
            InstQueueWr_Addr = (InstQueueWr_Addr + 1) & 15;
            if (StateBS16)
	    begin
		if (Datai[31]) a2 = -(-Datai >> 16);
		else           a2 = Datai >> 16;
		InstQueue[InstQueueWr_Addr] = a2 & 255;
		InstQueueWr_Addr = (InstQueueWr_Addr+ 1) & 15;
		if (Datai[31]) a2 = -(-Datai >> 24);
		else           a2 = Datai >> 24;
		InstQueue[InstQueueWr_Addr] = a2 & 255;
		InstQueueWr_Addr = (InstQueueWr_Addr + 1) & 15;
		PhyAddrPointer = PhyAddrPointer + 4;
		State2 = S5;
	    end
            else
	    begin
		PhyAddrPointer = PhyAddrPointer + 2;
		if (PhyAddrPointer[31]) //<0
			rEIP <= -PhyAddrPointer;
		else
			rEIP <= PhyAddrPointer;
		State2 = S3;
	    end
	end
	S3:
	begin
            RequestPending <= Pending;
	    if (!READY_n)
		State2 = S4;
	    else
		State2 = S3;
	end
	S4:
	begin
            RequestPending <= NotPending;
            InstQueue[InstQueueWr_Addr] = Datai & 255;
            InstQueueWr_Addr = (InstQueueWr_Addr + 1) & 15;
            InstQueue[InstQueueWr_Addr] = Datai & 255;
            InstQueueWr_Addr = (InstQueueWr_Addr + 1) & 15;
            PhyAddrPointer = PhyAddrPointer + 2;
	    State2 = S5;
	end
	S5:
	begin
            case (InstQueue[InstQueueRd_Addr])
                NOP:
		begin
                    InstAddrPointer = InstAddrPointer + 1;
                    InstQueueRd_Addr = (InstQueueRd_Addr + 1) & 15;
                    Flush = 0;
                    More = 0;
		end
                OPsop:
		begin
                    InstAddrPointer = InstAddrPointer + 1;
                    InstQueueRd_Addr = (InstQueueRd_Addr + 1) & 15;
                    Extended = 1;
                    Flush = 0;
                    More = 0;
		end
                JMP_rel_short:
		begin
                    if (InstQueueWr_Addr >= InstQueueRd_Addr+3)
		    begin
                        if (InstQueue[(InstQueueRd_Addr+1)&15] > 127)
			begin
                            PhyAddrPointer = InstAddrPointer + 1 - (8'hFF- InstQueue[(InstQueueRd_Addr+1)&15]);
                            InstAddrPointer = PhyAddrPointer;
			end
                        else
			begin
                            PhyAddrPointer = InstAddrPointer + 2 + InstQueue[(InstQueueRd_Addr+1)&15];
                            InstAddrPointer = PhyAddrPointer;
                        end
                        Flush = 1;
                        More = 0;
		    end
                    else
		    begin
                        Flush = 0;
                        More = 1;
                    end
		end
                JMP_rel_near:
		begin
                    if (InstQueueWr_Addr >= InstQueueRd_Addr+5)
		    begin
                        PhyAddrPointer = InstAddrPointer + 5 + InstQueue[(InstQueueRd_Addr +1)&15];
                        InstAddrPointer = PhyAddrPointer;
                        Flush = 1;
                        More = 0;
		    end
                    else
		    begin
                        Flush = 0;
                        More = 1;
                    end
		end
                JMP_intseg_immed:
		begin
                    InstAddrPointer = InstAddrPointer + 1;
                    InstQueueRd_Addr = (InstQueueRd_Addr + 1) & 15;
                    Flush = 0;
                    More = 0;
		end
                MOV_al_b:
		begin
                    InstAddrPointer = InstAddrPointer + 1;
                    InstQueueRd_Addr = (InstQueueRd_Addr+ 1) & 15;
                    Flush = 0;
                    More = 0;
		end
                MOV_eax_dw:
		begin
                    if (InstQueueWr_Addr >= InstQueueRd_Addr+5)
		    begin
                        EAX <= (InstQueue[(InstQueueRd_Addr+4)&15]<<23) + (InstQueue[(InstQueueRd_Addr+3)&15]<<16) + (InstQueue[(InstQueueRd_Addr+2)& 15]<<8) + InstQueue[(InstQueueRd_Addr+1)&15];
                        More = 0;
                        Flush = 0;
                        InstAddrPointer = InstAddrPointer + 5;
                        InstQueueRd_Addr = (InstQueueRd_Addr + 5) & 15;
		    end
                    else
		    begin
                        Flush = 0;
                        More = 1;
                    end
		end
                MOV_ebx_dw:
		begin
                    if (InstQueueWr_Addr >= InstQueueRd_Addr+5)
		    begin
                        EBX <= (InstQueue[(InstQueueRd_Addr+4) & 15]<<23) + (InstQueue[(InstQueueRd_Addr+3)&15]<<16) + (InstQueue[(InstQueueRd_Addr+2)& 15]<<8) + InstQueue[(InstQueueRd_Addr+1)&15]; //corrected!
                        More = 0;
                        Flush = 0;
                        InstAddrPointer = InstAddrPointer + 5;
                        InstQueueRd_Addr = (InstQueueRd_Addr + 5) & 15;
		    end
                    else
		    begin
                        Flush = 0;
                        More = 1;
                    end
		end
                MOV_eax_ebx:
		begin
                    if (InstQueueWr_Addr >= InstQueueRd_Addr+2)
		    begin
			if (EBX[31]) //<0
				rEIP <= -EBX;
			else
	                        rEIP <= EBX;
                        RequestPending <= Pending;
                        ReadRequest <= Pending;
                        MemoryFetch <= Pending;
                        CodeFetch <= NotPending;
			if (!READY_n)
			begin
                          RequestPending <= NotPending;
                          uWord = Datai & 16'h7fff;
                          if (StateBS16)
			  begin
                            // lWord = Datai/(1<<16);
			    // fs 062299
			    lWord = Datai & 16'hffff;
			  end
                          else
			  begin
                            rEIP <= rEIP + 2;
                            RequestPending <= Pending;
			    if (!READY_n)
			    begin
				RequestPending <= NotPending;
				lWord = Datai & 16'hffff;
			    end
                          end
			  if (!READY_n)
			  begin
                            EAX <= (uWord<<16) + lWord;
                            More = 0;
                            Flush = 0;
                            InstAddrPointer = InstAddrPointer + 2;
                            InstQueueRd_Addr = (InstQueueRd_Addr + 2) & 15;
			  end
			end
		    end
                    else
		    begin
                        Flush = 0;
                        More = 1;
                    end
		end
                MOV_ebx_eax:
		begin
                    if (InstQueueWr_Addr >= InstQueueRd_Addr+2)
		    begin
			if (EBX[31]) //<0
	                        rEIP <= -EBX; //corrected!
			else
	                        rEIP <= EBX;
                        lWord = EAX & 16'hffff;
			if (EAX[31]) a2 = -(-EAX >> 16);
			else         a2 = EAX >> 16;
                        uWord = a2 & 16'h7fff;
                        RequestPending <= Pending;
                        ReadRequest <= NotPending;
                        MemoryFetch <= Pending;
                        CodeFetch <= NotPending;
			if (State == StateT1 || State == StateT1P)
			begin
                          Datao <= (uWord<<16) + lWord;
			  if (!READY_n)
			  begin
                            RequestPending <= NotPending;
                            if (!StateBS16)
			    begin
                              rEIP <= rEIP + 2;
                              RequestPending <= Pending;
                              ReadRequest <= NotPending;
                              MemoryFetch <= Pending;
                              CodeFetch <= NotPending;
			      State2 =S6;
                            end
                            More = 0;
                            Flush = 0;
                            InstAddrPointer = InstAddrPointer + 2;
                            InstQueueRd_Addr = (InstQueueRd_Addr + 2) & 15;
			  end
			end
		    end
                    else
		    begin
                        Flush = 0;
                        More = 1;
                    end
		end
                IN_al:
		begin
                    if (InstQueueWr_Addr >= InstQueueRd_Addr+2)
		    begin
                        rEIP <= InstQueueRd_Addr+1;
                        RequestPending <= Pending;
                        ReadRequest <= Pending;
                        MemoryFetch <= NotPending;
                        CodeFetch <= NotPending;
			if (!READY_n)
			begin
                          RequestPending <= NotPending;
                          EAX <= Datai;
                          InstAddrPointer = InstAddrPointer + 2;
                          InstQueueRd_Addr = InstQueueRd_Addr + 2;
                          Flush = 0;
                          More = 0;
			end
		    end
                    else
		    begin
                        Flush = 0;
                        More = 1;
                    end
		end
                OUT_al:
		begin
                    if (InstQueueWr_Addr >= InstQueueRd_Addr+2)
		    begin
                        rEIP <= InstQueueRd_Addr+1;
                        RequestPending <= Pending;
                        ReadRequest <= NotPending;
                        MemoryFetch <= NotPending;
                        CodeFetch <= NotPending;
			if (State == StateT1 || State == StateT1P)
			begin
                            fWord = EAX & 16'hffff;
                            Datao <= fWord;
			    if (!READY_n)
			    begin
                        	RequestPending <= NotPending;
                        	InstAddrPointer = InstAddrPointer + 2;
                        	InstQueueRd_Addr = (InstQueueRd_Addr+2) & 15;
                        	Flush = 0;
                        	More = 0;
			    end
			end
		    end
                    else
		    begin
                        Flush = 0;
                        More = 1;
                    end
		end
                ADD_al_b:
		begin
                    InstAddrPointer = InstAddrPointer + 1;
                    InstQueueRd_Addr = (InstQueueRd_Addr + 1) & 15;
                    Flush = 0;
                    More = 0;
		end
                ADD_ax_w:
		begin
                    InstAddrPointer = InstAddrPointer + 1;
                    InstQueueRd_Addr = (InstQueueRd_Addr + 1) & 15;
                    Flush = 0;
                    More = 0;
		end
                ROL_al_1:
		begin
                    InstAddrPointer = InstAddrPointer + 2;
                    InstQueueRd_Addr = (InstQueueRd_Addr + 2) & 15;
                    Flush = 0;
                    More = 0;
		end
                ROL_al_n:
		begin
                    InstAddrPointer = InstAddrPointer + 2;
                    InstQueueRd_Addr = (InstQueueRd_Addr + 2) & 15;
                    Flush = 0;
                    More = 0;
		end
                INC_eax:
		begin
                    EAX <= EAX + 1;
                    InstAddrPointer = InstAddrPointer + 1;
                    InstQueueRd_Addr = (InstQueueRd_Addr + 1) & 15;
                    Flush = 0;
                    More = 0;
		end
                INC_ebx:
		begin
                    EBX <= EBX + 1;
                    InstAddrPointer = InstAddrPointer + 1;
                    InstQueueRd_Addr = (InstQueueRd_Addr + 1) & 15;
                    Flush = 0;
                    More = 0;
		end
                default:
		begin
                    InstAddrPointer = InstAddrPointer + 1;
                    InstQueueRd_Addr = (InstQueueRd_Addr + 1) & 15;
                    Flush = 0;
                    More = 0;
		end
            endcase
	    if (!(InstQueueRd_Addr < InstQueueWr_Addr) || (InstQueueLimit < InstQueueRd_Addr+4) || Flush || More)
		State2 = S7;
	end
	S6:
	begin
		Datao <= (uWord<<16) + lWord;
		if (!READY_n)
		begin
		    RequestPending <= NotPending;
		    State2 = S5;
		end
	end
	S7:
	begin
          if (Flush)
	  begin
            InstQueueRd_Addr = 1;
            InstQueueWr_Addr = 1;

	    if (InstAddrPointer[31]) //<0
		fWord = -InstAddrPointer;
	    else
	     	fWord = InstAddrPointer;

            if (fWord & 1)
                InstQueueRd_Addr = (InstQueueRd_Addr + (fWord & 3)) & 15;
          end
          if (InstQueueLimit < InstQueueRd_Addr+3)
	  begin
	    State2 = S8;
            InstQueueWr_Addr = 0;
	  end
	  else
	    State2 = S9;
	end
	S8:
	begin
	    if (InstQueueRd_Addr <= InstQueueLimit)
	    begin
                InstQueue[InstQueueWr_Addr] = InstQueue[InstQueueRd_Addr];
                InstQueueRd_Addr = (InstQueueRd_Addr + 1) & 15;
                InstQueueWr_Addr = (InstQueueWr_Addr + 1) & 15;
		State2 = S8;
	    end
	    else
	    begin
                InstQueueRd_Addr = 0;
		State2 = S9;
	    end
	end
	S9:
	begin
            rEIP <= PhyAddrPointer;
	    State2 = S1;
	end
	endcase
    end
//// P2
always @(posedge CLOCK)
    begin
	if (RESET)
	begin
	    ByteEnable <= 0;
	    NonAligned <= 0;
	end
	else
        case (DataWidth)
            WidthByte:
                case (rEIP & 3)
                    0: ByteEnable <= 4'b1110;
                    1: ByteEnable <= 4'b1101;
                    2: ByteEnable <= 4'b1011;
                    3: ByteEnable <= 4'b0111;
                endcase
            WidthWord:
                case (rEIP & 3)
                    0: begin
                         ByteEnable <= 4'b1100;
                         NonAligned <= NotPending;
		       end
                    1: begin
                         ByteEnable <= 4'b1001;
                         NonAligned <= NotPending;
		       end
                    2: begin
                         ByteEnable <= 4'b0011;
                         NonAligned <= NotPending;
		       end
                    3: begin
                         ByteEnable <= 4'b0111;
                         NonAligned <= Pending;
		       end
                endcase
            WidthDword:
                case (rEIP & 3)
                    0: begin
                         ByteEnable <= 4'b0000;
                         NonAligned <= NotPending;
		       end
                    1: begin
                         ByteEnable <= 4'b0001;
                         NonAligned <= Pending;
		       end
                    2: begin
                         NonAligned <= Pending;
                         ByteEnable <= 4'b0011;
		       end
                    3: begin
                         NonAligned <= Pending;
                         ByteEnable <= 4'b0111;
		       end
                endcase
        endcase
    end
endmodule

//////////

module b17(clock, reset, hold, na, bs16, ready1, ready2, datai,
           wr, dc, mio, ast1, ast2, address1, address2, datao);
input clock;
input reset;
input hold;
input na;
input bs16;
input ready1;
input ready2;
input [31:0] datai; //signed
output wr;
output dc;
output mio;
output ast1;
output ast2;
output [29:0] address1;
output [29:0] address2;
output [31:0] datao; //signed
/////
wire clock;
wire reset;
wire hold;
wire na;
wire bs16;
wire ready1;
wire ready2;
wire [31:0] datai;
reg wr;
reg dc;
reg mio;
reg ast1;
reg ast2;
reg [29:0] address1;
reg [29:0] address2;
reg [31:0] datao;
/////
wire wr1,wr2,wr3;
wire dc1,dc2,dc3;
wire mio1,mio2,mio3;
wire ads1,ads2,ads3;
wire [3:0] be1,be2,be3;
wire [29:0] addr1,addr2,addr3;
wire [31:0] do1,do2,do3; //signed
reg rdy1,rdy2,rdy3;
reg ready11,ready12,ready21,ready22;
reg [31:0] di1,di2,di3; //signed
reg [31:0] buf1,buf2; //signed
/////
b15  P1(clock, reset, na, bs16, rdy1, hold, di1,
	wr1, dc1, mio1, ads1, be1, addr1, do1);
b15  P2(clock, reset, na, bs16, rdy2, hold, di2,
	wr2, dc2, mio2, ads2, be2, addr2, do2);
b15  P3(clock, reset, na, bs16, rdy3, hold, di3,
	wr3, dc3, mio3, ads3, be3, addr3, do3);
/////
always @(addr1 or buf1 or datai)
begin
    if (addr1 > 32'h20000000)
	di1 <= buf1;
    else
	di1 <= datai;
end
/////
always @(addr2 or buf1 or buf2)
begin
    if (addr2 > 32'h20000000)
	di2 <= buf1;
    else
	di2 <= buf2;
end
/////
always @(addr2 or addr3 or do1 or do2 or do3)
begin
    if (do1 < 32'h40000000 && do2 < 32'h40000000 && do3 < 32'h40000000)
	address2 <= addr3;
    else
	address2 <= addr2;
end
/////
always @(buf2 or do3 or addr1 or wr3 or dc3 or mio3 or ads1 or ads3 or 
         ready1 or ready2 or ready11 or ready12 or ready21 or ready22)
begin
    di3 <= buf2;
    datao <= do3;
    address1 <= addr1;
    wr <= wr3;
    dc <= dc3;
    mio <= mio3;
    ast1 <= ads1;
    ast2 <= ads3;
    rdy1 <= ready11 & ready1;
    rdy2 <= ready12 & ready21;
    rdy3 <= ready22 & ready2;
end
/////
always @(posedge clock)
begin
    if (reset)
    begin
	buf1 <= 0;
	ready11 <= 0;
	ready12 <= 0;
    end
    else
    begin
	if (addr1>32'h20000000 && !ads1 && mio1 && !dc1 && wr1 && !be1)
	begin
	    buf1 <= do1;
	    ready11 <= 0;
	    ready12 <= 1;
	end
	else if (addr2>32'h20000000 && !ads2 && mio2 && !dc2 && wr2 && !be2)
	begin
	    buf1 <= do2;
	    ready11 <= 1;
	    ready12 <= 0;
	end
	else
	begin
	    ready11 <= 1;
	    ready12 <= 1;
	end
    end
end
/////
always @(posedge clock)
begin
    if (reset)
    begin
	buf2 <= 0;
	ready21 <= 0;
	ready22 <= 0;
    end
    else
    begin
	if (addr2 < 32'h20000000 && !ads2 && mio2 && !dc2 && wr2 && !be2)
	begin
	    buf2 <= do2;
	    ready21 <= 0;
	    ready22 <= 1;
	end
	else if (!ads3 && mio3 && !dc3 && !wr3 && !be3)
	begin
	    ready21 <= 1;
	    ready22 <= 0;
	end
	else
	begin
	    ready21 <= 1;
	    ready22 <= 1;
	end
    end
end

endmodule

//////////

module b18 (clock, reset, hold, na, bs, sel, din, aux, dout);
input clock;
input reset;
input hold;
input na;
input bs;
input sel;
input [31:0] din; //signed
output [2:0] aux;
output [19:0] dout;
/////
wire clock;
wire reset;
wire hold;
wire na;
wire bs;
wire sel;
wire [31:0] din; //signed
reg [2:0] aux;
reg [19:0] dout;
/////
reg r11,r12,r21,r22;
reg [31:0] di1,di2; //signed
wire wr1,wr2,dc1,dc2,mio1,mio2;
wire as11,as12,as21,as22;
wire [29:0] ad11,ad12,ad21,ad22;
wire [31:0] do1,do2; //signed

reg [31:0] di3,di4; //signed
wire rd3,rd4,wr3,wr4;
wire [19:0] ad31,ad41;
wire [31:0] do3,do4; //signed

reg [31:0] td1,td2; //signed
reg [29:0] tad1,tad2;
reg [19:0] tad3,tad4;
reg [31:0] a1,a2,product;
/////
b17  P1(clock,reset,hold,na,bs,r11,r12,di1,
        wr1,dc1,mio1,as11,as12,ad11,ad12,do1);
b17  P2(clock,reset,hold,na,bs,r21,r22,di2,
        wr2,dc2,mio2,as21,as22,ad21,ad22,do2);
b14  P3(clock,reset,di3,rd3,wr3,ad31,do3);
b14  P4(clock,reset,di4,rd4,wr4,ad41,do4);
/////
always @(wr1 or dc1 or mio1 or as11 or as12 or ad11 or ad12 or do1 or
         wr2 or dc2 or mio2 or as21 or as22 or ad21 or ad22 or do2 or
         rd3 or wr3 or ad31 or do3 or rd4 or wr4 or ad41 or do4 or
         sel or din or td1 or td2 or tad1 or tad2 or tad3 or tad4)
begin
    di3 <= do1 & 20'hfffff;

    r12 <= ~(rd3 & wr1 & mio1 & dc1 & ~as12);
    di4 <= do2;
    r22 <= ~(rd4 & wr2 & mio2 & dc2 & ~as22);
    r11 <= as21;
    r21 <= as11;
    if (wr3) tad3 <= ad31;
    else     tad3 <= tad2 & 20'hfffff;
    if (wr4) tad4 <= ad41;
    else     tad4 <= tad1 & 20'hfffff;
    if (!do3[31] && (do3 > 32'h10000000))
	tad1 <= ad11;
    else
	tad1 <= ad12;
    if (!do4[31] && (do4 > 32'h20000000))
	tad2 <= ad21;
    else
	tad2 <= ad22;
    dout <= (tad3 * tad4) & 20'hfffff;
    if (!sel)
    begin
	td1 <= 0;
	td2 <= din;
    end
    else
    begin
	td1 <= din;
	td2 <= 0;
    end
    if (do4[31]) a1 = -do4;
    else         a1 = do4;
    if (td1[31]) a2 = -td1;
    else         a2 = td1;
    product = a1 * a2;
    if (do4[31] ^ td1[31]) di1 = -product;
    else                   di1 = product;

    if (do3[31]) a1 = -do3;
    else         a1 = do3;
    if (td2[31]) a2 = -td2;
    else         a2 = td2;
    product = a1 * a2;
    if (do3[31] ^ td2[31]) di2 = -product;
    else                   di2 = product;

    aux = (tad1 * tad2) & 7;
end
endmodule


